package com.unitedvision.persistence.domain;

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;

import com.unitedvision.core.domain.Transaction;
import com.unitedvision.core.exception.WrongFormatException;

@Entity
@Table (name = "transaction")
public class TransactionEntity {
	private int id;
	private OperatorEntity operator;
	private InventoryEntity inventory;
	private CompanyCustomerEntity companyCustomer;
	private Date transactionDate;
	private int typeDescriptor;
	private int numberOfGoods;
	private long cost;
	
	public TransactionEntity() {
		super();
	}

	public TransactionEntity(Transaction transaction) throws WrongFormatException {
		super();
		this.id = transaction.getId();
		this.operator = OperatorEntity.create(transaction.getOperator());
		this.inventory = InventoryEntity.create(transaction.getInventory());
		this.companyCustomer = CompanyCustomerEntity.create(transaction.getCompanyCustomer());
		this.typeDescriptor = transaction.getTypeDescriptor();
		this.numberOfGoods = transaction.getNumberOfGoods();
		this.cost = transaction.getCost();
		this.transactionDate = transaction.getTransactionDate();
	}

	public TransactionEntity(OperatorEntity operator, InventoryEntity inventory, CompanyCustomerEntity companyCustomer, int typeDescriptor, int numberOfGoods, long cost, Date transactionDate) {
		super();
		this.operator = operator;
		this.inventory = inventory;
		this.companyCustomer = companyCustomer;
		this.typeDescriptor = typeDescriptor;
		this.numberOfGoods = numberOfGoods;
		this.cost = cost;
		this.transactionDate = transactionDate;
	}

	@Id @GeneratedValue
	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	@ManyToOne (fetch = FetchType.EAGER)
	@JoinColumn (name = "operator_id", referencedColumnName = "id")
	public OperatorEntity getOperator() {
		return operator;
	}

	public void setOperator(OperatorEntity operator) {
		this.operator = operator;
	}

	@ManyToOne (fetch = FetchType.EAGER)
	@JoinColumn (name = "inventory_id", referencedColumnName = "id")
	public InventoryEntity getInventory() {
		return inventory;
	}

	public void setInventory(InventoryEntity inventory) {
		this.inventory = inventory;
	}

	@ManyToOne (fetch = FetchType.EAGER)
	@JoinColumn (name = "company_customer_id", referencedColumnName = "id")
	public CompanyCustomerEntity getCompanyCustomer() {
		return companyCustomer;
	}

	public void setCompanyCustomer(CompanyCustomerEntity companyCustomer) {
		this.companyCustomer = companyCustomer;
	}

	@Temporal (TemporalType.DATE)
	@Column (name = "transaction_date")
	public Date getTransactionDate() {
		return transactionDate;
	}

	public void setTransactionDate(Date transactionDate) {
		this.transactionDate = transactionDate;
	}

	@Column (name = "type_descriptor")
	public int getTypeDescriptor() {
		return typeDescriptor;
	}

	public void setTypeDescriptor(int typeDescriptor) {
		this.typeDescriptor = typeDescriptor;
	}

	@Column (name = "number_of_goods")
	public int getNumberOfGoods() {
		return numberOfGoods;
	}

	public void setNumberOfGoods(int numberOfGoods) {
		this.numberOfGoods = numberOfGoods;
	}

	@Column (name = "cost")
	public long getCost() {
		return cost;
	}

	public void setCost(long cost) {
		this.cost = cost;
	}

	@Transient
	public CompanyEntity getCompany() {
		return companyCustomer.getCompany();
	}
	
	public Transaction toTransaction() {
		return new Transaction(id, operator.toOperator(), inventory.toInventory(), companyCustomer.toCompanyCustomer(), typeDescriptor, numberOfGoods, cost, transactionDate);
	}
	
	public static TransactionEntity create(OperatorEntity operator, InventoryEntity inventory, CompanyCustomerEntity companyCustomer, int typeDescriptor, int numberOfGoods, long cost, Date transactionDate) {
		return new TransactionEntity(operator, inventory, companyCustomer, typeDescriptor, numberOfGoods, cost, transactionDate);
	}

	public static TransactionEntity create(Transaction transaction) throws WrongFormatException {
		return new TransactionEntity(transaction);
	}

	@Override
	public String toString() {
		return "TransactionEntity [id=" + id + ", operator=" + operator
				+ ", inventory=" + inventory + ", companyCustomer="
				+ companyCustomer + ", typeDescriptor=" + typeDescriptor
				+ ", numberOfGoods=" + numberOfGoods + ", cost=" + cost + "]";
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result
				+ ((companyCustomer == null) ? 0 : companyCustomer.hashCode());
		result = prime * result + (int) (cost ^ (cost >>> 32));
		result = prime * result + id;
		result = prime * result
				+ ((inventory == null) ? 0 : inventory.hashCode());
		result = prime * result + numberOfGoods;
		result = prime * result
				+ ((operator == null) ? 0 : operator.hashCode());
		result = prime * result + typeDescriptor;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		TransactionEntity other = (TransactionEntity) obj;
		if (companyCustomer == null) {
			if (other.companyCustomer != null)
				return false;
		} else if (!companyCustomer.equals(other.companyCustomer))
			return false;
		if (cost != other.cost)
			return false;
		if (id != other.id)
			return false;
		if (inventory == null) {
			if (other.inventory != null)
				return false;
		} else if (!inventory.equals(other.inventory))
			return false;
		if (numberOfGoods != other.numberOfGoods)
			return false;
		if (operator == null) {
			if (other.operator != null)
				return false;
		} else if (!operator.equals(other.operator))
			return false;
		if (typeDescriptor != other.typeDescriptor)
			return false;
		return true;
	}
}
